package com.mt.baseinfo.until;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.beans.BeanCopier;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class BeanConvertUtils {
    private static ConcurrentHashMap<String,BeanCopier> copierCache = new ConcurrentHashMap();

    private static Logger logger = LoggerFactory.getLogger(BeanConvertUtils.class);

    /**
     * 拷贝源对象的属性到目标对象
     * @param source 源对象
     * @param target 目标对象
     * @return
     */
    public static <T, V> V copy(T source, V target) {
        return copy(source, target, false);
    }

    /**
     * 拷贝源对象的属性到目标类的实例，并返回目标类的实例
     * @param source 源对象
     * @param targetClazz  目标类
     * @return
     */
    public static <T, V> V convert(T source, Class<V> targetClazz) {
        if (source == null)
            return null;

        try {
            V targetObj = targetClazz.newInstance();
            return copy(source, targetObj, false);
        } catch (Exception e) {
            logger.error("BeanCopy ERROR : {} --> {}",source.getClass().getSimpleName(),targetClazz.getSimpleName());
            throw new RuntimeException(e);
        }
    }

    /**
     * 将源对象列表转换为目标类实例的列表
     * @param sources    源对象列表
     * @param targetClazz   目标类
     * @return
     */
    public static <T, V> List<V> convertList(List<T> sources, Class<V> targetClazz) {
        if (sources == null || sources.isEmpty())
            return null;

        List<V> targetList = new ArrayList();
        for (T sourceObj : sources) {
            try{
                V targetObj = convert(sourceObj, targetClazz);
                targetList.add(targetObj);
            } catch (Exception e) {
                logger.error("BeanCopy ERROR : List<{}> --> List<{}>",sourceObj.getClass().getSimpleName(),targetClazz.getSimpleName());
                e.printStackTrace();
                break;
            }
        }
        return targetList;
    }

    /**
     * 拷贝源对象的属性到目标对象
     * @param source 源对象
     * @param target 目标对象
     * @param useConvert 是否转换
     */
    public static <T,V> V copy(T source, V target, boolean useConvert){
        if (source == null || target == null)
            return null;
        try {
            String key = source.getClass().getSimpleName() + target.getClass().getSimpleName();
            BeanCopier copier = copierCache.get(key);
            if(copier == null){
                copier = createBeanCopier(source.getClass(), target.getClass(), useConvert, key);
            }
            copier.copy(source, target, null);
            return target;
        }
        catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    private static BeanCopier createBeanCopier(Class sourceClazz, Class targetClazz,
                                               boolean useConverter, String cacheKey) {
        BeanCopier copier = BeanCopier.create(sourceClazz,targetClazz,useConverter);
        copierCache.putIfAbsent(cacheKey,copier);
        return copier;
    }

}
